//
//  PixUtils.swift
//  DKE-Album
//
//  Created by dagny on 2025/9/26.
//  Copyright © 2025 杨东宝. All rights reserved.
//

//byteOrder32Big   大端模式 返回的  ABGR
//byteOrder32Littie   小端模式 返回的  RGBA


import Foundation
import UniformTypeIdentifiers
/*
 *  下面是由颜色代表值数据转换为ARGB值数 也就是转32位数值
 */

class PixUtils {
    
    //根据16灰阶颜色值，获取ABGR Uint32颜色值, 一个像素点需要4Bit，那一个字节可以转化为两个ABGR值，也就是两个像素点
    /*
     byte:字节，包含两个像素点，pix：byte的高4位或者地4位,返回Int  ABGR值
     */

   static func getArgbColorType_BW16_WithByte(byte:UInt8,pix:Int) -> UInt32 {
        var colorType:Int = 0
        let data:Int = Int(byte)
        if pix == 0 {
            //高4位
            colorType = (data & 0xf0) >> 4
        }else{
            //低4位
            colorType = (data & 0x0f)
        }
       return UInt32(0xFF000000 + 0x111111 * colorType);
    }
    static  func getArgbColorType_E6_WithByte(byte:UInt8,pix:Int) -> UInt32 {
        var colorType:Int = 0
        let data:Int = Int(byte)
        if pix == 0 {
            //高4位
            colorType = (data & 0xf0) >> 4
        }else{
            //低4位
            colorType = (data & 0x0f)
        }
        
        switch colorType {
        case 0:
            return 0xFF000000
        case 1:
            return 0xFFFFFFFF
        case 2:
            return  0xFF00FFFF
        case 3:
            return 0xFF0000FF
        case 5:
            return 0xFFFF0000
        case 6:
            return 0xFF00FF00
        default:
            return  0xFF000000
        }
    }
    static func getArgbColorType_E5_WithByte(byte:UInt8,pix:Int) -> UInt32 {
        var colorType:Int = 0
        let data:Int = Int(byte)
        if pix == 0 {    //高2位
            colorType = (data & 0xC0) >> 6
        }else if pix == 1{
            colorType = (data & 0x30) >> 4
        }else if pix == 2{
            colorType = (data & 0x0C) >> 2
        }else if pix == 3{
            colorType = (data & 0x03)
        }
        
        switch colorType {
        case 0:return  0xFF000000
        case 1:return 0xFFFFFFFF
        case 2:return  0xFF00FFFF
        case 3:return 0xFF0000FF
        default:
            return 0xFFFFFFFF
        }
    }
    static func getArgbColorType_7color_WithByte(byte0:UInt8,byte1:UInt8,pix:Int) -> UInt32 {
        var colorType:Int = 0
        let data0:Int = Int(byte0)
        let data1:Int = Int(byte1)
        if pix == 0 {    //高2位
            colorType = (((data0 & 0xC0) >> 6) << 2 ) + ((data1 & 0xC0) >> 6)
        }else if pix == 1{
            colorType = (((data0 & 0x30) >> 4) << 2 ) + ((data1 & 0x30) >> 4)
        }else if pix == 2{
            colorType = (((data0 & 0x0C) >> 2) << 2 ) + ((data1 & 0x0C) >> 2)
        }else if pix == 3{
            colorType = (((data0 & 0x03) >> 0) << 2 ) + ((data1 & 0x03) >> 0)
        }
        
        switch colorType {
        case 4:return  0xFF000000
        case 5:return  0xFFFFFFFF
        case 9:return  0xFF00FFFF
        case 13:return  0xFF0000FF
        case 1:return  0xFF007FFF
        case 7:return  0xFF7F7F7F
        case 6:return 0xFFA9A9A9
        default:
            return 0xFFFFFFFF
        }
    }
}

//bw16 4bit
func getOneByteWithBW16_uint32(pix1:UInt32,pix2:UInt32) -> UInt8{
  
    let oneByte = (get4bitForBWPix(pix:pix1) << 4) + get4bitForBWPix(pix:pix2)
    return oneByte
}
func get4bitForBWPix(pix:UInt32) -> UInt8 {
    if pix == 0xff000000 {
        return 0
    }else if(pix == 0xff111111){
        return 1
    }else if(pix == 0xff222222){
        return 2
    }else if(pix == 0xff333333){
        return 3
    }else if(pix == 0xff444444){
        return 4
    }else if(pix == 0xff555555){
        return 5
    }else if(pix == 0xff666666){
        return 6
    }else if(pix == 0xff777777){
        return 7
    }else if(pix == 0xff888888){
        return 8
    }else if(pix == 0xff999999){
        return 9
    }else if(pix == 0xffAAAAAA){
        return 10
    }else if(pix == 0xffBBBBBB){
        return 11
    }else if(pix == 0xffCCCCCC){
        return 12
    }else if(pix == 0xffDDDDDD){
        return 13
    }else if(pix == 0xffEEEEEE){
        return 14
    }else if(pix == 0xffFFFFFF){
        return 15
    }else{
        return 0
    }
}
//E6 4bit
func getOneByteWithE6_uint32(pix1:UInt32,pix2:UInt32) -> UInt8{
  
    let oneByte = (get4bitForE6Pix(pix:pix1) << 4) + get4bitForE6Pix(pix:pix2)
    return oneByte
    
}
func get4bitForE6Pix(pix:UInt32) -> UInt8 {
    if pix == 0xff000000 {
        return 0
    }else if(pix == 0xFFFFFFFF){
        return 1
    }else if(pix == 0xFF0000FF){
        return 3
    }else if(pix == 0xFF00FFFF){
        return 2
    }else if(pix == 0xFFFF0000){
        return 5
    }else if(pix == 0xFF00FF00){
        return 6
    }else{
        return 0
    }
}
//E5 2bit
func getOneByteWithE5_uint32(pix1:UInt32,pix2:UInt32,pix3:UInt32,pix4:UInt32) -> UInt8{
    let oneByte = (get2bitForE5Pix(pix:pix1) << 6) + (get2bitForE5Pix(pix:pix2) << 4) +  (get2bitForE5Pix(pix:pix3) << 2) + get2bitForE5Pix(pix:pix4)
    return oneByte
}
func get2bitForE5Pix(pix:UInt32) -> UInt8 {
    if pix == 0xff000000 {
        return 0
    }else if(pix == 0xFFFFFFFF){
        return 1
    }else if(pix == 0xFF0000FF){
        return 3
    }else if(pix == 0xFF00FFFF){
        return 2
    }else{
        return 0
    }
}
func getOneByteFor7C(pix1:UInt32,pix2:UInt32,pix3:UInt32,pix4:UInt32,isP1:Bool) ->UInt8{
    
    let oneByte = (get2bitFor7C(pix:pix1,isP1:isP1) << 6) + (get2bitFor7C(pix:pix2,isP1:isP1) << 4) +  (get2bitFor7C(pix:pix3,isP1:isP1) << 2) + get2bitFor7C(pix:pix4,isP1:isP1)
    return oneByte
    
}
func get2bitFor7C(pix:UInt32,isP1:Bool) -> UInt8 {
    
    if isP1 {
        if pix == 0xff000000 {
            return 1
        }else if(pix == 0xFFFFFFFF){
            return 1
        }else if(pix == 0xFF0000FF){
            return 3
        }else if(pix == 0xFF00FFFF){
            return 2
        }else if(pix == 0xFF007FFF){
            return 0
        }else if(pix == 0xFF7F7F7F){
            return 1
        }else if(pix == 0xFFA9A9A9){
            return 1
        }else{
            return 0
        }
    }else{
        if pix == 0xff000000 {
            return 1
        }else if(pix == 0xFFFFFFFF){
            return 1
        }else if(pix == 0xFF0000FF){
            return 1
        }else if(pix == 0xff00FFFF){
            return 1
        }else if(pix == 0xFF007FFF){
            return 1
        }else if(pix == 0xFF7F7F7F){
            return 3
        }else if(pix == 0xFFA9A9A9){
            return 2
        }else{
            return 0
        }
    }
    
}
/*
 *抖动算法
 */
func mutablePointerToArray<T>(_ pointer: UnsafeMutablePointer<T>, count: Int) -> [T] {
    let buffer = UnsafeBufferPointer(start: pointer, count: count)
    return Array(buffer)
}

func getProcessedImage(photoInfo:PhotoInforModel,screen:Screen,complate:(UIImage?)->Void){
        let dmtImage = ImageScaler.scaleImage(photoInfo.orgImage!, to: CGSize(width: screen.width , height:screen.height))
        var pixN:[ARGBPixel]!
        if photoInfo.isDtmChecked {
            if     screen.screenType == .ELECTRONICALBUM_1330_E6
                || screen.screenType == .ELECTRONICALBUM_2530_E6
                || screen.screenType == .ELECTRONICALBUM_2800_E6
                || screen.screenType == .ELECTRONICALBUM_3150_E6{
                //解析原图片数据
                var bgrValues = getAllPixelsBGR(image: dmtImage)
                let binPath = Bundle.main.path(forResource: "Spectra6_Render_LUT_Default_v2", ofType: "bin")
                bgrValues?.withUnsafeMutableBufferPointer { (point) -> Void in
                    if let srcAddress = point.baseAddress {
                      let tsb = einkdmt(srcAddress, Int32(screen.width), Int32(screen.height),binPath)
                        let buffer = UnsafeBufferPointer(start: tsb, count: screen.width * screen.height * 3)
                        DebugLog("buffer开始循环" + String(format: "\(Date().timeIntervalSince1970)"))
                        pixN = [ARGBPixel]()
                        for i in stride(from: 0, to: buffer.count, by: 3) {
                            pixN.append(ARGBPixel(a: 255.0, r: Float(buffer[i+2]), g: Float(buffer[i+1]), b: Float(buffer[i])))
                        }
                        DebugLog("buffer结束循环" + String(format: "\(Date().timeIntervalSince1970)"))
                        let dmtImage1 = getProcessBitmap(pixelsN:pixN, screen: screen)
                        complate(dmtImage1)
                    }
                }
            }else{
                pixN = getDmtImage(image: dmtImage!, screen: screen)
                let  dmtImage1 = getProcessBitmap(pixelsN:pixN, screen: screen)
                complate(dmtImage1)
            }
    }
}
     func getDmtImage(image:UIImage,screen:Screen) -> [ARGBPixel]{
        
        var newRgbs = [ARGBPixel]()
 
        let width = image.cgImage!.width;
        let height = image.cgImage!.height;
       
        var pixArray =  getABGRPixelData(from: image)
        
        var oldArgb:ARGBPixel?
        var newArgb:ARGBPixel?
        var errArgb:ARGBPixel?
        var pos:Int = 0
        if  screen.screenType == .ELECTRONICALBUM_0390_BW
            || screen.screenType == .ELECTRONICALBUM_2530_BW
            || screen.screenType == .ELECTRONICALBUM_3120_BW
            || screen.screenType == .ELECTRONICALBUM_4200_BW{
            
            newRgbs.removeAll()
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 17, g: 17, b: 17))
            newRgbs.append(ARGBPixel(a: 255, r: 34, g: 34, b: 34))
            newRgbs.append(ARGBPixel(a: 255, r: 51, g: 51, b: 51))
            newRgbs.append(ARGBPixel(a: 255, r: 68, g: 68, b: 68))
            newRgbs.append(ARGBPixel(a: 255, r: 85, g: 85, b: 85))
            newRgbs.append(ARGBPixel(a: 255, r: 102, g: 102, b: 102))
            newRgbs.append(ARGBPixel(a: 255, r: 119, g: 119, b: 119))
            newRgbs.append(ARGBPixel(a: 255, r: 136, g: 136, b: 136))
            newRgbs.append(ARGBPixel(a: 255, r: 153, g: 153, b: 153))
            newRgbs.append(ARGBPixel(a: 255, r: 170, g: 170, b: 170))
            newRgbs.append(ARGBPixel(a: 255, r: 187, g: 187, b: 187))
            newRgbs.append(ARGBPixel(a: 255, r: 204, g: 204, b: 204))
            newRgbs.append(ARGBPixel(a: 255, r: 221, g: 221, b: 221))
            newRgbs.append(ARGBPixel(a: 255, r: 238, g: 238, b: 238))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
        }else if screen.screenType == .ELECTRONICALBUM_1160_E5
                    || screen.screenType == .ELECTRONICALBUM_0970_E5{
            newRgbs.removeAll()
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
            
        }else if screen.screenType == .ELECTRONICALBUM_1330_E6
                    || screen.screenType == .ELECTRONICALBUM_2530_E6
                    || screen.screenType == .ELECTRONICALBUM_2800_E6
                    || screen.screenType == .ELECTRONICALBUM_3150_E6{
            newRgbs.removeAll()
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 255, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 255))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
        }else{
            newRgbs.removeAll()
            newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
            newRgbs.append(ARGBPixel(a: 255, r: 255, g: 127, b: 0))
            newRgbs.append(ARGBPixel(a: 255, r: 127, g: 127, b: 127))
            newRgbs.append(ARGBPixel(a: 255, r: 169, g: 169, b: 169))
        }
        
        for row in 0..<height {
            for col in 0..<width{
                pos = col + row * width
                let temp =  pixArray![pos]
                oldArgb = ARGBPixel(a: temp.a, r: temp.r, g: temp.g, b: temp.b);
                newArgb = getNearestColor2(oldArgb: oldArgb!, colors: newRgbs)
                pixArray![pos] = newArgb!
                errArgb = ARGBPixel(a: 255.0, r: oldArgb!.r - newArgb!.r, g: oldArgb!.g - newArgb!.g, b: oldArgb!.b - newArgb!.b);
                
                if col < width - 1 {
                    pos = (col + 1) + row * width
                    pixArray![pos] = calcNexPix2(oldPix: pixArray![pos], k: 7, errArgb: errArgb!)
                }
                
                if row < height - 1 {
                    if col > 0 {
                        pos = (col - 1) + (row + 1) * width
                        pixArray![pos] = calcNexPix2(oldPix: pixArray![pos], k: 3, errArgb: errArgb!)
                    }
                    
                    pos = col + (row + 1) * width
                    pixArray![pos] = calcNexPix2(oldPix: pixArray![pos], k: 5, errArgb: errArgb!)
                   
                    if col <  width - 1 {
                        pos = (col + 1) + (row + 1) * width
                        pixArray![pos] = calcNexPix2(oldPix: pixArray![pos], k: 1, errArgb: errArgb!)
                    }
                }
            }
        }
        return pixArray!
    }
    
     func getNearestColor2(oldArgb:ARGBPixel,colors:[ARGBPixel])->ARGBPixel{
        var nearARGB:ARGBPixel!
        var minDistance: CGFloat = .greatestFiniteMagnitude
        for newArgb in colors {
            let distance = getColorDistance2(oldArgb: oldArgb, newArgb: newArgb)
            if (distance! < minDistance) {
                minDistance = distance!;
                nearARGB = ARGBPixel(a: newArgb.a, r: newArgb.r, g: newArgb.g, b: newArgb.b);
            }
        }
        return nearARGB
    }
    
    // 计算与另一个颜色的欧几里得距离
     func getColorDistance2(oldArgb:ARGBPixel,newArgb:ARGBPixel) -> CGFloat? {
        let deltaR = oldArgb.r - newArgb.r
        let deltaG = oldArgb.g - newArgb.g
        let deltaB = oldArgb.b - newArgb.b
        
        return CGFloat(sqrt(deltaR * deltaR + deltaG * deltaG + deltaB * deltaB))
    }
    
    func calcNexPix2(oldPix:ARGBPixel,k:Float,errArgb:ARGBPixel) -> ARGBPixel {
        
       let d_tempR = oldPix.r
       let d_tempG = oldPix.g
       let d_tempB = oldPix.b
       
       let tempR = d_tempR + errArgb.r * k/16
       let tempG = d_tempG + errArgb.g * k/16
       let tempB = d_tempB + errArgb.b * k/16
        
       return ARGBPixel(a: 255.0, r: tempR, g: tempG, b: tempB)
   }
 
    func getProcessBitmap(pixelsN:[ARGBPixel],screen:Screen) -> UIImage? {
       var newRgbs = [ARGBPixel]()
       var pixN = [UInt32]()
       if  screen.screenType == .ELECTRONICALBUM_0390_BW
           || screen.screenType == .ELECTRONICALBUM_2530_BW
           || screen.screenType == .ELECTRONICALBUM_3120_BW
           || screen.screenType == .ELECTRONICALBUM_4200_BW{
           
           newRgbs.removeAll()
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 17, g: 17, b: 17))
           newRgbs.append(ARGBPixel(a: 255, r: 34, g: 34, b: 34))
           newRgbs.append(ARGBPixel(a: 255, r: 51, g: 51, b: 51))
           newRgbs.append(ARGBPixel(a: 255, r: 68, g: 68, b: 68))
           newRgbs.append(ARGBPixel(a: 255, r: 85, g: 85, b: 85))
           newRgbs.append(ARGBPixel(a: 255, r: 102, g: 102, b: 102))
           newRgbs.append(ARGBPixel(a: 255, r: 119, g: 119, b: 119))
           newRgbs.append(ARGBPixel(a: 255, r: 136, g: 136, b: 136))
           newRgbs.append(ARGBPixel(a: 255, r: 153, g: 153, b: 153))
           newRgbs.append(ARGBPixel(a: 255, r: 170, g: 170, b: 170))
           newRgbs.append(ARGBPixel(a: 255, r: 187, g: 187, b: 187))
           newRgbs.append(ARGBPixel(a: 255, r: 204, g: 204, b: 204))
           newRgbs.append(ARGBPixel(a: 255, r: 221, g: 221, b: 221))
           newRgbs.append(ARGBPixel(a: 255, r: 238, g: 238, b: 238))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
       }else if screen.screenType == .ELECTRONICALBUM_1160_E5
                   || screen.screenType == .ELECTRONICALBUM_0970_E5{
           newRgbs.removeAll()
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
           
       }else if screen.screenType == .ELECTRONICALBUM_1330_E6
                   || screen.screenType == .ELECTRONICALBUM_2530_E6
                   || screen.screenType == .ELECTRONICALBUM_2800_E6
                   || screen.screenType == .ELECTRONICALBUM_3150_E6{
           newRgbs.removeAll()
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 255, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 255))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
       }else{
           newRgbs.removeAll()
           newRgbs.append(ARGBPixel(a: 255, r: 0, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 0, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 255, b: 255))
           newRgbs.append(ARGBPixel(a: 255, r: 255, g: 127, b: 0))
           newRgbs.append(ARGBPixel(a: 255, r: 127, g: 127, b: 127))
           newRgbs.append(ARGBPixel(a: 255, r: 169, g: 169, b: 169))
       }
       for abgrPix in pixelsN {
           pixN.append(getNearestColor(oldArgb: abgrPix, colors: newRgbs))
       }
       return createImageFromIntColors(pixN, width: screen.width, height: screen.height)
   }
func getNearestColor(oldArgb:ARGBPixel,colors:[ARGBPixel])->UInt32{
   var nearARGB:ARGBPixel!
   var minDistance: CGFloat = .greatestFiniteMagnitude
   for newArgb in colors {
       let distance = getColorDistance(oldArgb: oldArgb, newArgb: newArgb)
       if (distance! < minDistance) {
           minDistance = distance!;
           nearARGB = ARGBPixel(a: newArgb.a, r: newArgb.r, g: newArgb.g, b: newArgb.b);
       }
   }
    return nearARGB.toUInt32()
}
func getABGRPixelData(from image: UIImage) -> [ARGBPixel]? {
      let cgImage = image.cgImage
      
      let width = cgImage?.width
      let height = cgImage?.height
      
      // 创建位图上下文
      let colorSpace = CGColorSpaceCreateDeviceRGB()
      let bitmapInfo = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue
      
      var pixelData = [UInt32](repeating: 0, count: width! * height!)
      
      guard let context = CGContext(
          data: &pixelData,
          width: width!,
          height: height!,
          bitsPerComponent: 8,
          bytesPerRow: width! * 4,
          space: colorSpace,
          bitmapInfo: bitmapInfo
      ) else { return nil }
      
      // 绘制图像到上下文
      context.draw(cgImage!, in: CGRect(x: 0, y: 0, width: width!, height: height!))
      
      // 转换为 ARGBPixel 数组
      let abgrPixels = pixelData.map { ARGBPixel(fromUInt32: $0) }
      return abgrPixels
}
func getIntPixelData(from image: UIImage) -> [UInt32]? {
   guard let cgImage = image.cgImage else { return nil }
   
   let width = cgImage.width
   let height = cgImage.height
   
   // 创建位图上下文
   let colorSpace = CGColorSpaceCreateDeviceRGB()
   let bitmapInfo = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue
   
   var pixelData = [UInt32](repeating: 0, count: width * height)
   
   guard let context = CGContext(
       data: &pixelData,
       width: width,
       height: height,
       bitsPerComponent: 8,
       bytesPerRow: width * 4,
       space: colorSpace,
       bitmapInfo: bitmapInfo
   ) else { return nil }
   
   // 绘制图像到上下文
   context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
   return pixelData
}
func getColorDistance(oldArgb:ARGBPixel,newArgb:ARGBPixel) -> CGFloat? {
    
    let rmean = (oldArgb.r + newArgb.r) / 2.0
    
    let weightR = 2.0 + rmean / 256.0
    let weightG:Float = 4.0
    let weightB = 2.0 + (255 - rmean) / 256.0
 
   let deltaR = oldArgb.r - newArgb.r
   let deltaG = oldArgb.g - newArgb.g
   let deltaB = oldArgb.b - newArgb.b
   
    let valueR = weightR * deltaR * deltaR
    let valueG = weightG * deltaG * deltaG
    let valueB = weightB * deltaB * deltaB
    
   return CGFloat(sqrt(valueR + valueG  + valueB))
    
}
//缩放图片
class ImageScaler {
    
    /// 缩放图片
    /// - Parameters:
    ///   - image: 原图片
    ///   - targetSize: 目标尺寸
    static func scaleImage(_ image: UIImage,
                          to targetSize: CGSize) -> UIImage? {
        return image.highQualityScaled(to: targetSize)
    }
}

extension UIImage {
    /// 使用 Core Graphics 高质量缩放
    func highQualityScaled(to size: CGSize) -> UIImage? {
        guard let cgImage = self.cgImage else { return nil }
        
        let bitsPerComponent = 8
        let bytesPerPixel = 4
        let bytesPerRow = bytesPerPixel * Int(size.width)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue
        
        guard let context = CGContext(
            data: nil,
            width: Int(size.width),
            height: Int(size.height),
            bitsPerComponent: bitsPerComponent,
            bytesPerRow: bytesPerRow,
            space: colorSpace,
            bitmapInfo: bitmapInfo
        ) else { return nil }
        
        // 设置高质量插值
        context.interpolationQuality = .high
        
        context.draw(cgImage, in: CGRect(origin: .zero, size: size))
        
        guard let scaledImage = context.makeImage() else { return nil }
        return UIImage(cgImage: scaledImage)
    }
    /// 使用 UIGraphicsImageRenderer 高质量缩放
       func resizedWithRenderer(to newSize: CGSize) -> UIImage? {
           let renderer = UIGraphicsImageRenderer(size: newSize)
           return renderer.image { context in
               self.draw(in: CGRect(origin: .zero, size: newSize))
           }
       }
}
// UIImage 转 BMP Data
func imageToBMPSimple(_ image: UIImage) -> Data? {
    guard let cgImage = image.cgImage else { return nil }
    
    let data = NSMutableData()
    guard let destination = CGImageDestinationCreateWithData(data, getBmpTypeIdentifier(), 1, nil) else { return nil }

    // 创建属性字典，明确指定格式选项
    let properties: [CFString: Any] = [
        kCGImagePropertyHasAlpha: false,
        kCGImagePropertyColorModel: kCGImagePropertyColorModelRGB
    ]
    
    CGImageDestinationAddImage(destination, cgImage, properties as CFDictionary)
    guard CGImageDestinationFinalize(destination) else {
            return nil
    }
    return data as Data
}

// BMP Data 转 UIImage - 修正版本
func bmpDataToUIImage(_ bmpData: Data) -> UIImage? {
    let options = [kCGImageSourceTypeIdentifierHint: getBmpTypeIdentifier()]
    guard let imageSource  = CGImageSourceCreateWithData(bmpData as CFData, options as CFDictionary), let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) else { return nil }
    return UIImage(cgImage: image)
}
func getBmpTypeIdentifier() -> CFString{
    if #available(iOS 14.0, *) {
        return UTType.bmp.identifier as CFString
    } else {
        return "com.microsoft.bmp" as CFString
    }
}
func getAllPixelsBGR(image:UIImage?) -> [UInt8]? {
    guard let cgImage = image?.cgImage else { return nil }
    
    let width = cgImage.width
    let height = cgImage.height
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue
    var pixelData = [UInt32](repeating: 0, count: width * height)
    
    guard let context = CGContext(
        data: &pixelData,
        width: width,
        height: height,
        bitsPerComponent: 8,
        bytesPerRow: width * 4,
        space: colorSpace,
        bitmapInfo: bitmapInfo
    ) else { return nil }
    
    
    context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
    
    var bgrDataValues = [UInt8]()
//    BGR
    for colorValue in pixelData {
        let components = extractColorComponents(from: colorValue)
        bgrDataValues.append(contentsOf: components)
    }

    return bgrDataValues
}

struct ARGBPixel {
    var a: Float // Alpha
    var r: Float // Red
    var g: Float // Green
    var b: Float // Blue
    
    init(a: Float, r: Float, g: Float, b: Float) {
        self.a = a
        self.r = r
        self.g = g
        self.b = b
    }
    
    init(fromUInt32 pixel: UInt32) {
        self.r = Float((pixel >> 0) & 0xFF)
        self.g = Float((pixel >> 8) & 0xFF)
        self.b = Float((pixel >> 16)  & 0xFF)
        self.a = Float((pixel >> 24) & 0xFF)
    }
    
    mutating func toUInt32() -> UInt32 {
        
        if(self.a > 255){
            self.a = 255.0
        }
        if(self.a < 0){
            self.a = 0.0
        }
        if(self.r > 255){
            self.r = 255.0
        }
        if(self.r < 0){
            self.r = 0
        }
        if(self.g > 255){
            self.g = 255.0
        }
        if(self.g < 0){
            self.g = 0
        }
        
        if(self.b > 255){
            self.b = 255.0
        }
        if(self.b < 0){
            self.b = 0
        }
        return (UInt32(a) << 24) | (UInt32(b) << 16) | (UInt32(g) << 8) | (UInt32(r) << 0)
    }
}
func createImageFromIntColors(_ colorValues: [UInt32],
                            width: Int,
                            height: Int) -> UIImage? {
    
    guard colorValues.count == width * height else {
        print("错误：颜色数组大小与图像尺寸不匹配")
        return nil
    }
    var pixelData = colorValues
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue //abgr
    guard let context = CGContext(data:&pixelData,
                                width: width,
                                height: height,
                                bitsPerComponent: 8,
                                bytesPerRow: width * 4,
                                space: colorSpace,
                                bitmapInfo: bitmapInfo) else {
        return nil
    }
    
    guard let cgImage = context.makeImage() else { return nil }
    return UIImage(cgImage: cgImage)
}
func scaleImage(image: UIImage, newSize: CGSize) -> UIImage? {
    
    // 创建绘图上下文，并设置缩放因子
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0) // 第三个参数 1.0 表示不针对屏幕进行缩放
    guard let context = UIGraphicsGetCurrentContext() else { return nil }
    
    // 关键步骤：关闭上下文插值
    context.interpolationQuality = .none
    image.draw(in: CGRect(origin: .zero, size: newSize))
    
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return newImage
}

// 提取颜色分量
private func extractColorComponents(from colorValue: UInt32) -> [UInt8] {
        let b = UInt8((colorValue >> 16) & 0xFF)
        let g = UInt8((colorValue >> 8) & 0xFF)
        let r = UInt8((colorValue >> 0) & 0xFF)
        return [b, g, r] // BGR
}







